package com.gmrz.uaf.remote.protocol.v1.validation.reg;

import com.gmrz.uaf.common.Constants;
import com.gmrz.uaf.protocol.v1.processor.exception.UAFErrorCode;
import com.gmrz.uaf.protocol.v1.schema.RegistrationResponse;
import com.gmrz.uaf.protocol.v1.schema.ServerChallenge;
import com.gmrz.uaf.protocol.v1.validaton.FCParamsValidator;
import com.gmrz.uaf.protocol.v1.validaton.OperationHeaderValidator;
import com.gmrz.uaf.protocol.v1.validaton.ValidationException;
import com.gmrz.uaf.protocol.v1.validaton.Validator;
import com.gmrz.uaf.protocol.v1.validaton.reg.RegResponseValidationException;
import com.gmrz.uaf.server.ServerConfig;
import com.gmrz.util.Strings;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by gongyuqiang on 2017/5/2.
 */
public class UAPRegResponseValidator implements Validator<RegistrationResponse> {
    private static final Logger LOG = LogManager.getLogger(UAPRegResponseValidator.class);
    List<Validator<?>> validationChain;

    public UAPRegResponseValidator(ServerConfig config, Constants.Operation op,String tenantId,String transType)
    {
        this.validationChain = new ArrayList<Validator<?>>();
        this.validationChain.add(new OperationHeaderValidator(config, op,tenantId,transType));
        this.validationChain.add(new FCParamsValidator(config,tenantId,transType));
    }

    public void validate(RegistrationResponse regResp)
            throws RegResponseValidationException
    {
        if (regResp.getOperationHeader() == null) {
            LOG.error("OperationHeader is not present in Reg response, rejecting the response.");
            throw new RegResponseValidationException(UAFErrorCode.PROTOCOL_HEADER_VALIDATION_FAILED);
        }

        if (Strings.isNullOrEmpty(regResp.getFCPBase64())) {
            LOG.error("FinalChallengeParams is not present in Reg response, rejecting the response.");
            throw new RegResponseValidationException(UAFErrorCode.PROTOCOL_FCP_VALIDATION_FAILED);
        }

        if (regResp.getRegistration() == null) {
            LOG.error("AuthenticatorRegistration is not present in Reg response, rejecting the response.");
            throw new RegResponseValidationException(UAFErrorCode.PROTOCOL_INVALID_REG_ASSERTION);
        }

        ServerChallenge sc = regResp.getFinalChallengeParams().getServerChallenge();
        if (sc == null) {
            LOG.error("FCP ServerChallenge is not present in Reg response, rejecting the response.");
            throw new RegResponseValidationException(UAFErrorCode.PROTOCOL_CHALLENGE_VALIDATION_FAILED);
        }
        for (Validator v : this.validationChain) {
            try {
                if ((v instanceof OperationHeaderValidator)) {
                    ((OperationHeaderValidator) v).setServerChallenge(sc);
                    ((OperationHeaderValidator) v).validate(regResp.getOperationHeader());
                } else if ((v instanceof FCParamsValidator)) {
                    ((FCParamsValidator) v).validate(regResp.getFinalChallengeParams());
                }
            } catch (ValidationException e) {
                LOG.error("Failed to validated Reg response", e);
                throw new RegResponseValidationException(e.getErrorCode());
            }
        }
    }
}
